#include "syntax_tree.h"
#include "semantic_analyzer.h"
#include "main_container.h"
#include "errors_warnings.h"
extern MainContainer * CompilerData;



// <trans_list_add> ~ ; <name> : <expression>  {;}
// Gr_TransListAdd__spSemiCol_Name_spColon_Expression
SemanticsBlockTransactionDetail * SemanticAnalyzer::ReadMBTransactionDetail(SyntaxTreeNode * transactionDetailNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBTransactionDetail");
#endif

    SemanticsBlockTransactionDetail * sb;

    if (transactionDetailNode->Production == Gr_TransListAdd__spSemiCol_Name_spColon_Expression)
    {
        sb = new SemanticsBlockTransactionDetail();

        // <trans_list_add> ~ ; <name> : <expression>
        sb->TransactionName = GatherFromNameNode(transactionDetailNode->Nodes->GetData(1));
        sb->Expression = GatherFromExpression(transactionDetailNode->Nodes->GetData(3));
    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }

#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBTransactionDetail");
#endif

    return sb;
}





// <trans_list> ~ <name> : <expression> <trans_list_adds>
// Gr_TransList__Name_spColon_Expression_TransListAdds
GenericTable<SemanticsBlockTransactionDetail> * SemanticAnalyzer::GatherFromTransactionListNode(SyntaxTreeNode * transactionDetailNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("GatherTransactionList");
#endif

    GenericTable<SemanticsBlockTransactionDetail> * transactionDetails;
    

    // check production validity
    if (transactionDetailNode->Production == Gr_TransList__Name_spColon_Expression_TransListAdds)
    {
        transactionDetails = new GenericTable<SemanticsBlockTransactionDetail>();

        // <trans_list> ~ <name> : <expression> <trans_list_adds>  {NAME}
        SemanticsBlockTransactionDetail * sb = new SemanticsBlockTransactionDetail();
        sb->TransactionName = GatherFromNameNode(transactionDetailNode->Nodes->GetData(0));
        sb->Expression = GatherFromExpression(transactionDetailNode->Nodes->GetData(2));
        transactionDetails->Add(sb);


        SyntaxTreeNode * trans_list_adds = transactionDetailNode->Nodes->GetData(2);
        // <trans_list_adds> ~ <trans_list_add> <trans_list_adds>  {;}
        // <trans_list_adds> ~ ? {)}
        if (trans_list_adds->Production != Gr_TransListAdds__epsilon)
        {
            do
            {
                SyntaxTreeNode * trans_list_add = trans_list_adds->Nodes->GetData(0);
                transactionDetails->Add(ReadMBTransactionDetail(trans_list_add));

                // set next item in list
                trans_list_adds = trans_list_adds->Nodes->GetData(1);
            }
            while (trans_list_adds->Nodes->GetData(1)->Production != Gr_TransListAdds__epsilon);
        }
        

    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }

#ifdef TRACE
    CompilerData->LogTrace->ReportExit("GatherTransactionList");
#endif

    return transactionDetails;
}



// Gr_GenerateBlock__generate_UptoExpression_GenerateTransactions_AfterExpression_EveryExpression_spSemiCol
//  <generate_block> ~ generate <upto_expression> <generate_transactions> <after_expression> <every_expression> ;
// Gr_GpssBlock__GenerateBlock
//  <gpss_block> ~ <generate_block>
SemanticsBlockGenerate * SemanticAnalyzer::ReadMBGenerate(SyntaxTreeNode * mbGenerateNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBGenerate");
#endif

    SemanticsBlockGenerate * sb;

    // check production validity
    if (mbGenerateNode->Production == Gr_GpssBlock__GenerateBlock)
    {
        // <gpss_block> ~ <generate_block>
        sb = ReadMBGenerate(mbGenerateNode->Nodes->GetData(0));
    }
    else if (mbGenerateNode->Production == Gr_GenerateBlock__generate_UptoExpression_GenerateTransactions_AfterExpression_EveryExpression_spSemiCol)
    {
        sb = new SemanticsBlockGenerate();


        // <generate_block> ~ generate <upto_expression> <generate_transactions> <after_expression> <every_expression> ;
        


        // <upto_expression> ~ upto <expression>
        // <upto_expression> ~ ?
        SyntaxTreeNode * upto_expression = mbGenerateNode->Nodes->GetData(1); 
        if (upto_expression->Production == Gr_UptoExpression__epsilon)
            sb->UptoExpression = NULL;
        else if (upto_expression->Production == Gr_UptoExpression__upto_Expression)
            sb->UptoExpression = GatherFromExpression(upto_expression->Nodes->GetData(1));
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }

 

        // <generate_transactions> ~ <name> ( <trans_list> )  {NAME}
        // <generate_transactions> ~ <name>  {NAME}
        // <generate_transactions> ~ ? {after, every, ;, send}
        SyntaxTreeNode * generate_transactions = mbGenerateNode->Nodes->GetData(2); 
        if (generate_transactions->Production == Gr_GenerateTransactions__Name_spLPar_TransList_spRPar)
        {
            sb->TransactionName = GatherFromNameNode(generate_transactions->Nodes->GetData(0));
            
            delete sb->TransactionList;
            sb->TransactionList = GatherFromTransactionListNode(generate_transactions->Nodes->GetData(2));
        }
        else if (generate_transactions->Production == Gr_GenerateTransactions__Name)
        {
            sb->TransactionName = GatherFromNameNode(generate_transactions->Nodes->GetData(0));
            
            //sb->TransactionList = NULL;
            delete sb->TransactionList;
        }
        else if (generate_transactions->Production == Gr_GenerateTransactions__epsilon)
        {
            //sb->TransactionName = NULL;
            delete sb->TransactionName;
            //sb->TransactionList = NULL;
            delete sb->TransactionList;
        }
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }
        



      	// <after_expression> ~ after <expression>  {after}
        // <after_expression> ~ ? {every, ;, send}
        SyntaxTreeNode * after_expression = mbGenerateNode->Nodes->GetData(3); 
        if (after_expression->Production == Gr_AfterExpression__after_Expression)
        {
            sb->AfterExpression = GatherFromExpression(after_expression->Nodes->GetData(1));
        }
        else if (after_expression->Production == Gr_AfterExpression__epsilon)
        {
            sb->AfterExpression = NULL;
        }
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }



        // <every_expression> ~ every <expression> <plus_minus_expression>
        // <every_expression> ~ ?
        // <plus_minus_expression> ~ +- <expression>
	    // <plus_minus_expression> ~ ?
        SyntaxTreeNode * every_expression = mbGenerateNode->Nodes->GetData(4); 
        if (every_expression->Production == Gr_EveryExpression__epsilon)
        {
            sb->EveryExpressionMean = NULL;
            sb->EveryExpressionDeviation = NULL;
        }
        else if (every_expression->Production == Gr_EveryExpression__every_Expression_PlusMinusExpression)
        {
            sb->EveryExpressionMean = GatherFromExpression(every_expression->Nodes->GetData(1));
            
            SyntaxTreeNode * plus_minus_expression = every_expression->Nodes->GetData(2); 
            if (plus_minus_expression->Production == Gr_PlusMinusExpression__epsilon)
            {
                sb->EveryExpressionDeviation = NULL;
            }
            else if (plus_minus_expression->Production == Gr_PlusMinusExpression__spPlusMinus_Expression)
            {
                sb->EveryExpressionDeviation = GatherFromExpression(plus_minus_expression->Nodes->GetData(1));
            }
            else
            {
                // ERROR has been found
                // MAKE LOGICAL RECOVERING
            }

        }
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }






    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }

#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBGenerate");
#endif

    return sb;
}; 





// <gpss_block> ~ <create_block>
// Gr_GpssBlock__CreateBlock
//
// <create_block> ~ create <upto_expression> <generate_transactions> <after_expression> <every_expression> <send_to> ; 
// Gr_CreateBlock__create_UptoExpression_GenerateTransactions_AfterExpression_EveryExpression_SendTo_spSemiCol)
SemanticsBlockCreate * SemanticAnalyzer::ReadMBCreate(SyntaxTreeNode * mbCreateNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBCreate");
#endif

    SemanticsBlockCreate * sb;

    // check production validity
    if (mbCreateNode->Production == Gr_GpssBlock__CreateBlock)
    {
        // <gpss_block> ~ <create_block>
        sb = ReadMBCreate(mbCreateNode->Nodes->GetData(0));
    }
    else if (mbCreateNode->Production == Gr_CreateBlock__create_UptoExpression_GenerateTransactions_AfterExpression_EveryExpression_SendTo_spSemiCol)
    {
        sb = new SemanticsBlockCreate();


        // <create_block> ~ create <upto_expression> <generate_transactions> <after_expression> <every_expression> <send_to> ; 
        


        // <upto_expression> ~ upto <expression>
        // <upto_expression> ~ ?
        SyntaxTreeNode * upto_expression = mbCreateNode->Nodes->GetData(1); 
        if (upto_expression->Production == Gr_UptoExpression__epsilon)
            sb->UptoExpression = NULL;
        else if (upto_expression->Production == Gr_UptoExpression__upto_Expression)
            sb->UptoExpression = GatherFromExpression(upto_expression->Nodes->GetData(1));
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }

 

        // <generate_transactions> ~ <name> ( <trans_list> )  {NAME}
        // <generate_transactions> ~ <name>  {NAME}
        // <generate_transactions> ~ ? {after, every, ;, send}
        SyntaxTreeNode * generate_transactions = mbCreateNode->Nodes->GetData(2); 
        if (generate_transactions->Production == Gr_GenerateTransactions__Name_spLPar_TransList_spRPar)
        {
            sb->TransactionName = GatherFromNameNode(generate_transactions->Nodes->GetData(0));
            
            delete sb->TransactionList;
            sb->TransactionList = GatherFromTransactionListNode(generate_transactions->Nodes->GetData(2));
        }
        else if (generate_transactions->Production == Gr_GenerateTransactions__Name)
        {
            sb->TransactionName = GatherFromNameNode(generate_transactions->Nodes->GetData(0));
            
            //sb->TransactionList = NULL;
            delete sb->TransactionList;
        }
        else if (generate_transactions->Production == Gr_GenerateTransactions__epsilon)
        {
            //sb->TransactionName = NULL;
            delete sb->TransactionName;
            //sb->TransactionList = NULL;
            delete sb->TransactionList;
        }
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }
        



      	// <after_expression> ~ after <expression>  {after}
        // <after_expression> ~ ? {every, ;, send}
        SyntaxTreeNode * after_expression = mbCreateNode->Nodes->GetData(3); 
        if (after_expression->Production == Gr_AfterExpression__after_Expression)
        {
            sb->AfterExpression = GatherFromExpression(after_expression->Nodes->GetData(1));
        }
        else if (after_expression->Production == Gr_AfterExpression__epsilon)
        {
            sb->AfterExpression = NULL;
        }
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }



        // <every_expression> ~ every <expression> <plus_minus_expression>
        // <every_expression> ~ ?
        // <plus_minus_expression> ~ +- <expression>
	    // <plus_minus_expression> ~ ?
        SyntaxTreeNode * every_expression = mbCreateNode->Nodes->GetData(4); 
        if (every_expression->Production == Gr_EveryExpression__epsilon)
        {
            sb->EveryExpressionMean = NULL;
            sb->EveryExpressionDeviation = NULL;
        }
        else if (every_expression->Production == Gr_EveryExpression__every_Expression_PlusMinusExpression)
        {
            sb->EveryExpressionMean = GatherFromExpression(every_expression->Nodes->GetData(1));
            
            SyntaxTreeNode * plus_minus_expression = every_expression->Nodes->GetData(2); 
            if (plus_minus_expression->Production == Gr_PlusMinusExpression__epsilon)
            {
                sb->EveryExpressionDeviation = NULL;
            }
            else if (plus_minus_expression->Production == Gr_PlusMinusExpression__spPlusMinus_Expression)
            {
                sb->EveryExpressionDeviation = GatherFromExpression(plus_minus_expression->Nodes->GetData(1));
            }
            else
            {
                // ERROR has been found
                // MAKE LOGICAL RECOVERING
            }

        }
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }



        // <send_to> ~ send to <name>
        // <send_to> ~ ?
	    // Gr_SendTo__send_to_Name,
        // Gr_SendTo__epsilon,
        SyntaxTreeNode * send_to = mbCreateNode->Nodes->GetData(5); 
        if (send_to->Production == Gr_SendTo__epsilon)
        {
            //sb->SendToName = NULL;
            delete sb->SendToName;
        }
        else if (send_to->Production == Gr_SendTo__send_to_Name)
        {
            sb->SendToName = GatherFromNameNode(send_to->Nodes->GetData(1));
        }
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }



    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }

#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBCreate");
#endif

    return sb;
}






// <gpss_block> ~ <split_block>
// Gr_GpssBlock__SplitBlock
//
// <split_block> ~ split <into_expression> <send_to> ;
// Gr_SplitBlock__split_IntoExpression_SendTo_spSemiCol
SemanticsBlockSplit * SemanticAnalyzer::ReadMBSplit(SyntaxTreeNode * mbSplitNode)
{

#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMBSplit");
#endif

    SemanticsBlockSplit * sb;

    // check production validity
    if (mbSplitNode->Production == Gr_GpssBlock__SplitBlock)
    {
        // <gpss_block> ~ <split_block>
        sb = ReadMBSplit(mbSplitNode->Nodes->GetData(0));
    }
    else if (mbSplitNode->Production == Gr_SplitBlock__split_IntoExpression_SendTo_spSemiCol)
    {
        sb = new SemanticsBlockSplit();


        // <split_block> ~ split <into_expression> <send_to> ;
        


        // <into_expression> ~ into <expression>
        // <into_expression> ~ ?
        SyntaxTreeNode * into_expression = mbSplitNode->Nodes->GetData(1); 
        if (into_expression->Production == Gr_IntoExpression__epsilon)
            sb->ExpressionInto = NULL;
        else if (into_expression->Production == Gr_IntoExpression__into_Expression)
            sb->ExpressionInto = GatherFromExpression(into_expression->Nodes->GetData(1));
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }

 
        // <send_to> ~ send to <name>
        // <send_to> ~ ?
	    // Gr_SendTo__send_to_Name,
        // Gr_SendTo__epsilon,
        SyntaxTreeNode * send_to = mbSplitNode->Nodes->GetData(2); 
        if (send_to->Production == Gr_SendTo__epsilon)
        {
            //sb->SendToName = NULL;
            delete sb->SendToName;
        }
        else if (send_to->Production == Gr_SendTo__send_to_Name)
        {
            sb->SendToName = GatherFromNameNode(send_to->Nodes->GetData(1));
        }
        else
        {
            // ERROR has been found
            // MAKE LOGICAL RECOVERING
        }



    }
    else
    {
        // ERROR has been found
        // MAKE LOGICAL RECOVERING
    }

#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMBSplit");
#endif

    return sb;

}